# -*- coding: utf-8 -*-
<#
.SYNOPSIS
    Ansible and AWX Installation Script for CentOS 9

.DESCRIPTION
    This script generates installation scripts on the local system, copies them to the target server,
    and executes them remotely via SSH to install Ansible and AWX on the control node (192.168.144.132).
    
    The script follows this workflow:
    1. Generate Ansible installation script locally
    2. Generate AWX installation script locally
    3. Copy scripts to the control node via SCP
    4. Execute scripts remotely via SSH
    5. Clean up temporary files

.NOTES
    Author: PowerShell Automation Script
    Date: $(Get-Date)
    Requires: SSH key-based authentication to be configured
    Target OS: CentOS 9
#>

# Set UTF-8 encoding for PowerShell console
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8

# ============================================================================
# CONFIGURATION PARAMETERS
# ============================================================================

# Target server configuration
$controlNode = "192.168.144.132"  # Ansible control node IP
$username = "zenglg"               # SSH username
$scriptDir = "E:\ansible-centos9\scripts"  # Local directory for generated scripts
$imagesDir = "E:\ansible-centos9\docker-images"  # Local directory for Docker images

# Docker images configuration
$dockerImages = @(
    "quay.io/ansible/awx:24.2.0",
    "postgres:13",
    "redis:7",
    "quay.io/ansible/awx-operator:2.7.2"
)

# Logging configuration
$logFile = "E:\ansible-centos9\install_log_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"

# ============================================================================
# LOGGING FUNCTIONS
# ============================================================================

<#
.SYNOPSIS
    Write log message with timestamp and level

.DESCRIPTION
    Writes formatted log messages to both console and log file
    Supports different log levels: INFO, ERROR, SUCCESS, WARNING

.PARAMETER Message
    The message to log

.PARAMETER Level
    Log level (INFO, ERROR, SUCCESS, WARNING)
#>
function Write-Log {
    param(
        [string]$Message,
        [string]$Level = "INFO"
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logMessage = "[$timestamp] [$Level] $Message"
    
    # Write to console with color coding
    switch ($Level) {
        "ERROR" { Write-Host $logMessage -ForegroundColor Red }
        "SUCCESS" { Write-Host $logMessage -ForegroundColor Green }
        "WARNING" { Write-Host $logMessage -ForegroundColor Yellow }
        default { Write-Host $logMessage -ForegroundColor White }
    }
    
    # Write to log file
    try {
        $logMessage | Out-File -FilePath $logFile -Append -Encoding UTF8
    }
    catch {
        Write-Host "Failed to write to log file: $($_.Exception.Message)" -ForegroundColor Red
    }
}

# ============================================================================
# UTILITY FUNCTIONS
# ============================================================================

<#
.SYNOPSIS
    Create directory for generated scripts

.DESCRIPTION
    Creates the local directory where installation scripts will be generated
    Ensures the directory exists and is writable
#>
function New-ScriptDirectory {
    Write-Log "Creating script directory: $scriptDir"
    
    try {
        if (-not (Test-Path $scriptDir)) {
            New-Item -ItemType Directory -Path $scriptDir -Force | Out-Null
            Write-Log "Script directory created successfully" "SUCCESS"
        } else {
            Write-Log "Script directory already exists" "INFO"
        }
        return $true
    }
    catch {
        Write-Log "Failed to create script directory: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

<#
.SYNOPSIS
    Create directory for Docker images

.DESCRIPTION
    Creates the local directory where Docker images will be stored
    Ensures the directory exists and is writable
#>
function New-ImagesDirectory {
    Write-Log "Creating Docker images directory: $imagesDir"
    
    try {
        if (-not (Test-Path $imagesDir)) {
            New-Item -ItemType Directory -Path $imagesDir -Force | Out-Null
            Write-Log "Docker images directory created successfully" "SUCCESS"
        } else {
            Write-Log "Docker images directory already exists" "INFO"
        }
        return $true
    }
    catch {
        Write-Log "Failed to create Docker images directory: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

<#
.SYNOPSIS
    Download Docker images on Windows

.DESCRIPTION
    Downloads required Docker images on Windows machine for offline transfer
    Uses Docker Desktop or Docker CLI to pull and save images
#>
function Get-DockerImages {
    Write-Log "Starting Docker images download process"
    
    # Check if Docker is available
    try {
        $dockerVersion = docker --version 2>$null
        if ($LASTEXITCODE -ne 0) {
            Write-Log "Docker is not installed or not available" "ERROR"
            return $false
        }
        Write-Log "Docker detected: $dockerVersion"
    }
    catch {
        Write-Log "Failed to check Docker availability: $($_.Exception.Message)" "ERROR"
        return $false
    }
    
    # Create images directory
    if (-not (New-ImagesDirectory)) {
        return $false
    }
    
    # Download and save each Docker image
    foreach ($image in $dockerImages) {
        $imageName = $image.Split('/')[-1].Replace(':', '_')
        $imageFile = Join-Path $imagesDir "$imageName.tar"
        
        Write-Log "Processing image: $image"
        
        # Check if image file already exists
        if (Test-Path $imageFile) {
            Write-Log "Image file already exists: $imageFile" "INFO"
            continue
        }
        
        try {
            # Pull the image
            Write-Log "Pulling Docker image: $image"
            $pullOutput = docker pull $image 2>&1
            if ($LASTEXITCODE -ne 0) {
                Write-Log "Failed to pull image $image : $pullOutput" "ERROR"
                continue
            }
            
            # Save the image to tar file
            Write-Log "Saving image to: $imageFile"
            $saveOutput = docker save -o $imageFile $image 2>&1
            if ($LASTEXITCODE -ne 0) {
                Write-Log "Failed to save image $image : $saveOutput" "ERROR"
                continue
            }
            
            Write-Log "Successfully saved image: $imageName.tar" "SUCCESS"
        }
        catch {
            Write-Log "Error processing image $image : $($_.Exception.Message)" "ERROR"
            continue
        }
    }
    
    Write-Log "Docker images download process completed" "SUCCESS"
    return $true
}

<#
.SYNOPSIS
    Transfer Docker images to target server

.DESCRIPTION
    Transfers Docker image tar files to the target server via SCP
    Creates remote directory and copies all image files
#>
function Copy-DockerImages {
    param(
        [string]$ServerIP,
        [string]$Username
    )
    
    Write-Log "Starting Docker images transfer to $ServerIP"
    
    # Check if images directory exists
    if (-not (Test-Path $imagesDir)) {
        Write-Log "Docker images directory not found: $imagesDir" "ERROR"
        return $false
    }
    
    # Get list of image files
    $imageFiles = Get-ChildItem -Path $imagesDir -Filter "*.tar"
    if ($imageFiles.Count -eq 0) {
        Write-Log "No Docker image files found in $imagesDir" "WARNING"
        return $true
    }
    
    try {
        # Create remote directory for images
        $createDirCommand = "ssh -o StrictHostKeyChecking=no $Username@$ServerIP 'mkdir -p /tmp/docker-images'"
        Write-Log "Creating remote directory: $createDirCommand"
        Invoke-Expression $createDirCommand
        
        # Transfer each image file
        foreach ($imageFile in $imageFiles) {
            $remotePath = "/tmp/docker-images/$($imageFile.Name)"
            $scpCommand = "scp -o StrictHostKeyChecking=no `"$($imageFile.FullName)`" ${Username}@${ServerIP}:${remotePath}"
            
            Write-Log "Transferring: $($imageFile.Name)"
            $output = Invoke-Expression $scpCommand 2>&1
            
            if ($LASTEXITCODE -eq 0) {
                Write-Log "Successfully transferred: $($imageFile.Name)" "SUCCESS"
            } else {
                Write-Log "Failed to transfer $($imageFile.Name): $output" "ERROR"
                return $false
            }
        }
        
        Write-Log "All Docker images transferred successfully" "SUCCESS"
        return $true
    }
    catch {
        Write-Log "Error transferring Docker images: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

# ============================================================================
# SCRIPT GENERATION FUNCTIONS
# ============================================================================

<#
.SYNOPSIS
    Generate Ansible installation script for CentOS 9

.DESCRIPTION
    Creates a bash script that installs Ansible and its dependencies on CentOS 9
    Includes package updates, EPEL installation, Python setup, and Ansible configuration

.OUTPUTS
    Returns the path to the generated script file
#>
function New-AnsibleInstallScript {
    $ansibleScript = @'
#!/bin/bash
# Ansible Installation Script for CentOS 9
# Generated by PowerShell automation script

set -e

echo "Starting Ansible installation on CentOS 9..."
echo "Date: $(date)"
echo "User: $(whoami)"
echo "Hostname: $(hostname)"

# Check if Python3 is available
echo "Checking Python3 availability..."
if ! command -v python3 &> /dev/null; then
    echo "Python3 is not installed. Please install Python3 first."
    echo "Run: sudo dnf install -y python3 python3-pip python3-devel"
    exit 1
fi

# Check if pip is available
echo "Checking pip availability..."
if ! python3 -m pip --version &> /dev/null; then
    echo "pip is not available. Attempting to install pip..."
    python3 -m ensurepip --user
    if ! python3 -m pip --version &> /dev/null; then
        echo "Failed to install pip. Please install pip manually."
        echo "Run: sudo dnf install -y python3-pip"
        exit 1
    fi
fi

# Check git availability (optional for basic Ansible installation)
echo "Checking git availability..."
if ! command -v git &> /dev/null; then
    echo "Warning: git is not installed. Some Ansible features may require git."
    echo "Continuing with Ansible installation without git..."
    echo "To install git later, run as root: dnf install -y git"
else
    echo "git is available: $(git --version)"
fi

# Install Ansible via pip
echo "Installing Ansible via pip..."
python3 -m pip install --user ansible

# Add pip bin directory to PATH
echo "Configuring PATH..."
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
export PATH="$HOME/.local/bin:$PATH"

# Verify Ansible installation
echo "Verifying Ansible installation..."
ansible --version

# Create Ansible configuration directory
echo "Creating Ansible configuration..."
mkdir -p ~/ansible

# Create basic ansible.cfg
cat > ~/ansible/ansible.cfg << "ANSIBLE_CFG_EOF"
[defaults]
inventory = ./inventory
host_key_checking = False
remote_user = zenglg
private_key_file = ~/.ssh/id_rsa

[inventory]
enable_plugins = host_list, script, auto, yaml, ini, toml
ANSIBLE_CFG_EOF

# Create inventory file
cat > ~/ansible/inventory << "INVENTORY_EOF"
[control]
192.168.144.132

[managed]
192.168.144.133
192.168.144.134

[centos:children]
control
managed
INVENTORY_EOF

echo "Ansible installation completed successfully!"
echo "Configuration files created in ~/ansible/"
echo "Inventory file: ~/ansible/inventory"
echo "Config file: ~/ansible/ansible.cfg"
'@
    
    $scriptPath = "$scriptDir\install_ansible.sh"
    # Write script content to file with Unix line endings
    $ansibleScript -replace "`r`n", "`n" | Out-File -FilePath $scriptPath -Encoding UTF8 -NoNewline
    Add-Content -Path $scriptPath -Value "`n" -NoNewline
    Write-Log "Generated Ansible installation script: $scriptPath"
    return $scriptPath
}

<#
.SYNOPSIS
    Generate AWX installation script for CentOS 9

.DESCRIPTION
    Creates a bash script that installs AWX using Minikube and the AWX Operator
    Includes Docker, kubectl, Minikube setup, and AWX deployment

.OUTPUTS
    Returns the path to the generated script file
#>
function New-AWXInstallScript {
    $awxScript = @'
#!/bin/bash
# -*- coding: utf-8 -*-
# AWX Docker Installation Script for CentOS 9
# Generated by PowerShell automation script
# Author: PowerShell Automation Script
# Date: $(date)
# Description: Install AWX using Docker Compose on CentOS 9

set -e

# ============================================================================
# LOGGING FUNCTIONS
# ============================================================================

# Function to log messages with timestamp
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] [AWX] $1"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] [AWX] $1" >&2
}

log_success() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] [AWX] $1"
}

# ============================================================================
# MAIN INSTALLATION PROCESS
# ============================================================================

log "Starting AWX Docker installation on CentOS 9..."
log "Date: $(date)"
log "User: $(whoami)"
log "Hostname: $(hostname)"

# Check if running as root
if [ "$EUID" -eq 0 ]; then
    log_error "This script should not be run as root. Please run as a regular user with sudo privileges."
    exit 1
fi

# Check if Docker is installed and running
log "Checking Docker installation..."
if ! command -v docker &> /dev/null; then
    log_error "Docker is not installed. Please install Docker first."
    exit 1
fi

if ! sudo systemctl is-active --quiet docker; then
    log "Starting Docker service..."
    sudo systemctl start docker
    sudo systemctl enable docker
fi

# Check if docker-compose is available
log "Checking docker-compose installation..."
if ! command -v docker-compose &> /dev/null; then
    log "Installing docker-compose..."
    sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose
    sudo ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose
fi

# Load Docker images if available
log "Loading Docker images from /tmp/docker-images..."
if [ -d "/tmp/docker-images" ]; then
    for image_file in /tmp/docker-images/*.tar; do
        if [ -f "$image_file" ]; then
            log "Loading image: $(basename "$image_file")"
            sudo docker load -i "$image_file"
        fi
    done
else
    log "No offline images found, will pull from registry"
fi

# Create AWX deployment directory
log "Creating AWX deployment directory..."
mkdir -p ~/awx-docker
cd ~/awx-docker

# Create docker-compose.yml for AWX
log "Creating AWX docker-compose configuration..."
cat > docker-compose.yml << 'COMPOSE_EOF'
version: '3.8'

services:
  awx-web:
    image: quay.io/ansible/awx:24.2.0
    container_name: awx_web
    depends_on:
      - awx-postgres
      - awx-redis
    ports:
      - "80:8052"
    hostname: awxweb
    user: root
    restart: unless-stopped
    volumes:
      - awx-projects:/var/lib/awx/projects:rw
      - awx-custom-ca-trust:/etc/pki/ca-trust/source/anchors:rw
      - awx-settings:/etc/tower:rw
    environment:
      - DATABASE_HOST=awx-postgres
      - DATABASE_PORT=5432
      - DATABASE_NAME=awx
      - DATABASE_USER=awx
      - DATABASE_PASSWORD=awx_password_123
      - REDIS_HOST=awx-redis
      - REDIS_PORT=6379
      - SECRET_KEY=awx_secret_key_very_long_and_secure_12345
      - AWX_ADMIN_USER=admin
      - AWX_ADMIN_PASSWORD=admin123
    command: ["/usr/bin/launch_awx.sh"]

  awx-task:
    image: quay.io/ansible/awx:24.2.0
    container_name: awx_task
    depends_on:
      - awx-postgres
      - awx-redis
    hostname: awx
    user: root
    restart: unless-stopped
    volumes:
      - awx-projects:/var/lib/awx/projects:rw
      - awx-custom-ca-trust:/etc/pki/ca-trust/source/anchors:rw
      - awx-settings:/etc/tower:rw
    environment:
      - DATABASE_HOST=awx-postgres
      - DATABASE_PORT=5432
      - DATABASE_NAME=awx
      - DATABASE_USER=awx
      - DATABASE_PASSWORD=awx_password_123
      - REDIS_HOST=awx-redis
      - REDIS_PORT=6379
      - SECRET_KEY=awx_secret_key_very_long_and_secure_12345
      - AWX_ADMIN_USER=admin
      - AWX_ADMIN_PASSWORD=admin123
    command: ["/usr/bin/launch_awx_task.sh"]

  awx-postgres:
    image: postgres:13
    container_name: awx_postgres
    restart: unless-stopped
    volumes:
      - awx-postgres-data:/var/lib/postgresql/data:Z
    environment:
      - POSTGRES_USER=awx
      - POSTGRES_PASSWORD=awx_password_123
      - POSTGRES_DB=awx
      - PGDATA=/var/lib/postgresql/data/pgdata

  awx-redis:
    image: redis:7
    container_name: awx_redis
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - awx-redis-data:/data:Z

volumes:
  awx-postgres-data:
  awx-redis-data:
  awx-projects:
  awx-custom-ca-trust:
  awx-settings:
COMPOSE_EOF

# Configure firewall for AWX access
log "Configuring firewall for AWX access..."
sudo firewall-cmd --permanent --add-port=80/tcp 2>/dev/null || true
sudo firewall-cmd --permanent --add-port=8052/tcp 2>/dev/null || true
sudo firewall-cmd --reload 2>/dev/null || true

# Stop any existing AWX containers
log "Stopping any existing AWX containers..."
docker-compose down 2>/dev/null || true

# Start AWX services using docker-compose
log "Starting AWX services with docker-compose..."
docker-compose up -d

# Wait for services to start
log "Waiting for AWX services to start (this may take a few minutes)..."
sleep 60

# Check if services are running
if docker-compose ps | grep -q "Up"; then
    log_success "AWX containers started successfully!"
    
    # Show container status
    log "Container Status:"
    docker-compose ps
    
    # Wait for AWX to fully initialize
    log "Waiting for AWX to fully initialize..."
    sleep 120
    
    # Test AWX accessibility
    for i in {1..15}; do
        if curl -s -o /dev/null -w "%{http_code}" http://localhost | grep -q "200\|302\|403"; then
            log_success "AWX Web interface is accessible!"
            break
        else
            log "Waiting for AWX to be ready... (attempt $i/15)"
            sleep 20
        fi
    done
    
    log_success "AWX Docker installation completed successfully!"
    log "AWX Web Interface: http://$(hostname -I | awk '{print $1}')"
    log "Default Login: admin / admin123"
    log "Database: PostgreSQL running in container"
    log "Cache: Redis running in container"
    log "All services are containerized and managed by Docker Compose"
    
    echo "AWX Docker installation completed successfully!"
    echo "AWX Web Interface: http://$(hostname -I | awk '{print $1}')"
    echo "Default Login: admin / admin123"
    echo "Database: PostgreSQL running in container"
    echo "Cache: Redis running in container"
    echo "All services are containerized and managed by Docker Compose"
    echo ""
    echo "=== AWX ACCESS INFORMATION ==="
    echo "URL: http://$(hostname -I | awk '{print $1}')"
    echo "Username: admin"
    echo "Password: admin123"
    echo ""
    echo "To manage AWX services:"
    echo "- Start: cd ~/awx-docker && docker-compose up -d"
    echo "- Stop: cd ~/awx-docker && docker-compose down"
    echo "- Logs: cd ~/awx-docker && docker-compose logs -f"
else
    log_error "Failed to start AWX containers"
    log "Container logs:"
    docker-compose logs 2>/dev/null || echo "No logs available"
    exit 1
fi
'@
    
    $scriptPath = "$scriptDir\install_awx.sh"
    # Write script content to file with Unix line endings
    $awxScript -replace "`r`n", "`n" | Out-File -FilePath $scriptPath -Encoding UTF8 -NoNewline
    Add-Content -Path $scriptPath -Value "`n" -NoNewline
    Write-Log "Generated AWX installation script: $scriptPath"
    return $scriptPath
}

# ============================================================================
# REMOTE EXECUTION FUNCTIONS
# ============================================================================

<#
.SYNOPSIS
    Copy script to remote server

.DESCRIPTION
    Copies the generated script to the target server using SCP
    Sets proper execute permissions on the remote script

.PARAMETER ScriptPath
    Local path to the script file

.PARAMETER RemotePath
    Remote path where script should be copied

.PARAMETER ServerIP
    Target server IP address

.PARAMETER Username
    SSH username for connection
#>
function Copy-ScriptToServer {
    param(
        [string]$ScriptPath,
        [string]$RemotePath,
        [string]$ServerIP,
        [string]$Username
    )
    
    Write-Log "Copying script to server: $ServerIP"
    
    try {
        # Copy script using SCP
        $scpCommand = "scp -o StrictHostKeyChecking=no `"$ScriptPath`" $Username@${ServerIP}:$RemotePath"
        Write-Log "Executing: $scpCommand"
        
        $result = Invoke-Expression $scpCommand
        
        if ($LASTEXITCODE -eq 0) {
            Write-Log "Script copied successfully to $ServerIP" "SUCCESS"
            
            # Set execute permissions
            $chmodCommand = "ssh -o StrictHostKeyChecking=no $Username@$ServerIP 'chmod +x $RemotePath'"
            Write-Log "Setting execute permissions: $chmodCommand"
            
            $chmodResult = Invoke-Expression $chmodCommand
            
            if ($LASTEXITCODE -eq 0) {
                Write-Log "Execute permissions set successfully" "SUCCESS"
                return $true
            } else {
                Write-Log "Failed to set execute permissions" "ERROR"
                return $false
            }
        } else {
            Write-Log "Failed to copy script to $ServerIP" "ERROR"
            return $false
        }
    }
    catch {
        Write-Log "Script copy error: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

<#
.SYNOPSIS
    Execute script remotely on server

.DESCRIPTION
    Executes the copied script on the remote server via SSH
    Captures and logs the execution output

.PARAMETER RemotePath
    Remote path to the script file

.PARAMETER ServerIP
    Target server IP address

.PARAMETER Username
    SSH username for connection

.PARAMETER LogPrefix
    Prefix for log messages from remote execution
#>
function Invoke-RemoteScript {
    param(
        [string]$RemotePath,
        [string]$ServerIP,
        [string]$Username,
        [string]$LogPrefix = "Remote"
    )
    
    Write-Log "Executing script remotely on server: $ServerIP"
    Write-Log "Remote script path: $RemotePath"
    
    try {
        # Execute script remotely via SSH
        $sshCommand = "ssh -o StrictHostKeyChecking=no $Username@$ServerIP '/bin/bash $RemotePath'"
        Write-Log "Executing: $sshCommand"
        
        # Execute and capture output
        $output = Invoke-Expression $sshCommand 2>&1
        $exitCode = $LASTEXITCODE
        
        # Log the output
        if ($output) {
            $output | ForEach-Object {
                Write-Log "[$LogPrefix] $_" "INFO"
            }
        }
        
        if ($exitCode -eq 0) {
            Write-Log "Script executed successfully on $ServerIP" "SUCCESS"
            return $true
        } else {
            Write-Log "Script execution failed on $ServerIP (Exit Code: $exitCode)" "ERROR"
            return $false
        }
    }
    catch {
        Write-Log "Remote script execution error: $($_.Exception.Message)" "ERROR"
        return $false
    }
}

# ============================================================================
# MAIN PROGRAM EXECUTION
# ============================================================================

try {
    Write-Log "Starting Ansible and AWX Docker installation process" "INFO"
    Write-Log "Target control node: $controlNode"
    Write-Log "Username: $username"
    Write-Log "Script directory: $scriptDir"
    Write-Log "Docker images directory: $imagesDir"
    
    # Step 1: Create script directory
    Write-Log "Step 1: Creating script directory" "INFO"
    if (-not (New-ScriptDirectory)) {
        throw "Failed to create script directory"
    }
    
    # Step 2: Download Docker images (optional, skip if Docker not available)
    Write-Log "Step 2: Downloading Docker images (optional)" "INFO"
    $imagesDownloaded = Get-DockerImages
    if ($imagesDownloaded) {
        Write-Log "Docker images downloaded successfully" "SUCCESS"
    } else {
        Write-Log "Docker images download skipped or failed, will use online images" "WARNING"
    }
    
    # Step 3: Generate Ansible installation script
    Write-Log "Step 3: Generating Ansible installation script" "INFO"
    $ansibleScriptPath = New-AnsibleInstallScript
    if (-not (Test-Path $ansibleScriptPath)) {
        throw "Failed to generate Ansible installation script"
    }
    
    # Step 4: Generate AWX installation script
    Write-Log "Step 4: Generating AWX Docker installation script" "INFO"
    $awxScriptPath = New-AWXInstallScript
    if (-not (Test-Path $awxScriptPath)) {
        throw "Failed to generate AWX installation script"
    }
    
    # Step 5: Copy Ansible script to control node
    Write-Log "Step 5: Copying Ansible script to control node" "INFO"
    $remoteAnsiblePath = "/tmp/install_ansible.sh"
    if (-not (Copy-ScriptToServer -ScriptPath $ansibleScriptPath -RemotePath $remoteAnsiblePath -ServerIP $controlNode -Username $username)) {
        throw "Failed to copy Ansible script to control node"
    }
    
    # Step 6: Execute Ansible installation
    Write-Log "Step 6: Executing Ansible installation on control node" "INFO"
    if (-not (Invoke-RemoteScript -RemotePath $remoteAnsiblePath -ServerIP $controlNode -Username $username -LogPrefix "Ansible")) {
        throw "Failed to install Ansible on control node"
    }
    
    # Step 7: Transfer Docker images to control node (if available)
    Write-Log "Step 7: Transferring Docker images to control node" "INFO"
    $imagesTransferred = Copy-DockerImages -ServerIP $controlNode -Username $username
    if ($imagesTransferred) {
        Write-Log "Docker images transferred successfully" "SUCCESS"
    } else {
        Write-Log "Docker images transfer skipped or failed, will use online images" "WARNING"
    }
    
    # Step 8: Copy AWX script to control node
    Write-Log "Step 8: Copying AWX Docker script to control node" "INFO"
    $remoteAWXPath = "/tmp/install_awx.sh"
    if (-not (Copy-ScriptToServer -ScriptPath $awxScriptPath -RemotePath $remoteAWXPath -ServerIP $controlNode -Username $username)) {
        throw "Failed to copy AWX script to control node"
    }
    
    # Step 9: Execute AWX Docker installation
    Write-Log "Step 9: Executing AWX Docker installation on control node" "INFO"
    if (-not (Invoke-RemoteScript -RemotePath $remoteAWXPath -ServerIP $controlNode -Username $username -LogPrefix "AWX")) {
        throw "Failed to install AWX on control node"
    }
    
    # Step 10: Cleanup temporary scripts on remote server
    Write-Log "Step 10: Cleaning up temporary scripts on remote server" "INFO"
    $cleanupCommand = "ssh -o StrictHostKeyChecking=no $username@$controlNode 'rm -f $remoteAnsiblePath $remoteAWXPath'"
    Invoke-Expression $cleanupCommand
    
    Write-Log "Ansible and AWX Docker installation completed successfully!" "SUCCESS"
    Write-Log "AWX Web Interface: http://$controlNode" "INFO"
    Write-Log "Default Login: admin / admin123" "INFO"
    Write-Log "Please check the AWX access information in the logs above" "INFO"
    
}
catch {
    Write-Log "Installation failed: $($_.Exception.Message)" "ERROR"
    exit 1
}
finally {
    Write-Log "Installation process finished at $(Get-Date)" "INFO"
}